package com.bwton.msx.ccb.ui;

import com.bwton.msx.ccb.R;
import com.bwton.msx.ccb.widget.camera.SenseCamera;
import com.bwton.msx.ccb.widget.camera.SenseCameraPreview;
import com.bwton.msx.ccb.widget.FaceOverlayView;
import com.sensetime.ssidmobile.sdk.liveness.constants.STImageOrientation;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

public abstract class AbstractCameraActivity extends BaseActivity
        implements PreviewCallback {

    protected static final int WIDTH = SenseCamera.DEFAULT_PREVIEW_SIZE.getWidth();
    protected static final int HEIGHT = SenseCamera.DEFAULT_PREVIEW_SIZE.getHeight();

    protected SenseCameraPreview mCameraPreview;
    protected TextView mTxtHint;
    protected FaceOverlayView mFaceOverlayView;
    private SenseCamera mSenseCamera;

    private int mCameraID;
    protected int mFaceOrientation = STImageOrientation.RIGHT;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camrea);
        mCameraPreview = findViewById(R.id.cameraPreview);
        mTxtHint = findViewById(R.id.hint);
        mFaceOverlayView = findViewById(R.id.faceOverlayView);
        findViewById(R.id.back).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        initCamera(SenseCamera.CAMERA_FACING_FRONT);
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSenseCamera.release();
    }

    private void initCamera(int cameraID) {
        mCameraID = cameraID;
        mFaceOrientation = getCameraOrigin(mCameraID);
        if (mSenseCamera != null) {
            this.mSenseCamera.release();
        }
        this.mSenseCamera = new SenseCamera.Builder(this)
                .setCameraId(mCameraID)
                .setFacing(mCameraID)
                .setRequestedPreviewSize(WIDTH, HEIGHT)
                .build();
        try {
            this.mCameraPreview.start(this.mSenseCamera);
            this.mSenseCamera.setOnPreviewFrameCallback(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void changeHint(@StringRes final int res) {
        changeHint(getString(res));
    }

    public void changeHint(final String hint) {
        mTxtHint.post(
                new Runnable() {
                    @Override
                    public void run() {
                        mTxtHint.setText(hint);
                    }
                }
        );
    }


    // 根据取景框裁剪图像帧
    protected Bitmap getCropPreview(byte[] bytes, int width, int height, Rect apertureRect) {
        Bitmap cropBitmap = null;
        if (apertureRect != null) {
            YuvImage yuvimage = new YuvImage(bytes, ImageFormat.NV21, width, height, null);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, byteArrayOutputStream);
            Bitmap origin = BitmapFactory.decodeByteArray(byteArrayOutputStream.toByteArray(), 0, byteArrayOutputStream.toByteArray().length);
            try {
                byteArrayOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Matrix matrix = new Matrix();
            matrix.setRotate(-90);
            if (origin != null) {
                // 围绕原地进行旋转
                Bitmap rotateBitmap = Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
                origin.recycle();
                if (rotateBitmap != null) {
                    cropBitmap = Bitmap.createBitmap(rotateBitmap, apertureRect.left, apertureRect.top, apertureRect.width(), apertureRect.height());
                    rotateBitmap.recycle();
                }
            }
        }
        return cropBitmap;
    }

    public @STImageOrientation
    int getCameraOrigin(int cameraId) {
        final WindowManager windowManager = (WindowManager)
                this.getSystemService(Context.WINDOW_SERVICE);
        int degrees = 0;
        int rotation = windowManager != null ?
                windowManager.getDefaultDisplay().getRotation() : Surface.ROTATION_0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
            default:
                break;
        }
        final Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        Camera.getCameraInfo(cameraId, cameraInfo);
        int angle;
        int displayAngle;
        if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            angle = (cameraInfo.orientation + degrees) % 360;
            displayAngle = (360 - angle) % 360;
        } else {  // back-facing
            angle = (cameraInfo.orientation - degrees + 360) % 360;
            displayAngle = angle;
        }

        switch (angle) {
            case 0:
                return STImageOrientation.UP;
            case 90:
                return STImageOrientation.LEFT;
            case 180:
                return STImageOrientation.DOWN;
            case 270:
                return STImageOrientation.RIGHT;
        }
        return STImageOrientation.RIGHT;
    }
}